package com.logic.landseaserver.models.payment.impl;

import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.logic.common.security.SecurityUtils;
import com.logic.common.util.CurrentThread;
import com.logic.landseaserver.common.LandeaConstants.QueryUesdCodeType;
import com.logic.landseaserver.common.LandeaConstants.ReRentType;
import com.logic.landseaserver.common.enums.BillStatusEnum;
import com.logic.landseaserver.common.enums.ContractStatusCodeEnum;
import com.logic.landseaserver.common.exception.LandseaException;
import com.logic.landseaserver.common.exception.ResultCodes.PaymentResultCode;
import com.logic.landseaserver.common.util.FileTool;
import com.logic.landseaserver.domain.Bill;
import com.logic.landseaserver.domain.BillDetail;
import com.logic.landseaserver.domain.BillPayment;
import com.logic.landseaserver.domain.Contract;
import com.logic.landseaserver.domain.Project;
import com.logic.landseaserver.models.authcode.service.AuthCodeService;
import com.logic.landseaserver.models.independent.service.BillIndependentService;
import com.logic.landseaserver.models.payment.PaymentConstant;
import com.logic.landseaserver.models.payment.PaymentConstant.BillTypeCode;
import com.logic.landseaserver.models.payment.bean.PaymentHelperBean;
import com.logic.landseaserver.models.payment.service.AbstractPaymentResponseHandler;
import com.logic.landseaserver.models.payment.service.PaymentService;
import com.logic.landseaserver.models.prepayment.bean.AddAccountObject;
import com.logic.landseaserver.models.prepayment.bean.AotuPayBill;
import com.logic.landseaserver.models.prepayment.bean.CurrentAccount;
import com.logic.landseaserver.models.prepayment.service.PrepaymentService;
import com.logic.landseaserver.persistence.read.BillDetailReadMapper;
import com.logic.landseaserver.persistence.read.ContractReadMapper;
import com.logic.landseaserver.persistence.read.ProjectReadMapper;
import com.logic.landseaserver.persistence.write.BillDetailWriteMapper;
import com.logic.landseaserver.persistence.write.BillWriteMapper;
import com.logic.landseaserver.persistence.write.ContractWriteMapper;
import com.logic.landseaserver.service.IBillService;
import com.logic.landseaserver.service.IDdLockService;
import com.logic.landseaserver.ws.dto.BillDTO;
import com.logic.landseaserver.ws.dto.BillDetailDTO;
import com.logic.system.domain.SystemFile;
import com.logic.system.persistence.write.FileWriteMapper;
import com.logic.system.service.IFileService;

/**
 * 
 *
 * 项目名称：system-server</br>
 * 类名称：FirstPayResponseHandler</br>
 * 类描述：首期账单结果通知处理</br>
 * 创建人：Aaron</br>
 * 创建时间：2017年7月19日 下午4:33:21</br>
 * 
 * @version 1.0
 *
 */
@Service(BillTypeCode.FIRST_PAY + PaymentConstant.PAYMENT_RESPONSE_SUFFIX)
public class FirstPayResponseHandler extends AbstractPaymentResponseHandler
{
    @Autowired
    private ProjectReadMapper projectReadMapper;
    
    @Autowired
    private ContractReadMapper contractReadMapper;
    
    @Autowired
    private ContractWriteMapper contractWriteMapper;
    
    @Autowired
    private BillWriteMapper billWriteMapper;
    
    @Autowired
    private PaymentService paymentService;
    
    @Autowired
    private IFileService fileService;
    
    @Autowired
    private FileWriteMapper fileWriteMapper;
    
    @Autowired
    private BillIndependentService billIndependentService;
    
    @Autowired
    private BillDetailReadMapper billDetailReadMapper;
    
    @Autowired
    private BillDetailWriteMapper billDetailWriteMapper;
    
    @Autowired
    private AuthCodeService authCodeService;
    
    @Autowired
    private PrepaymentService prepaymentService;
    
    @Autowired
    private IBillService billService;
    
    @Autowired
    private IDdLockService ddLockService;
    
    @Override
    protected void doLocalBusiness(BillPayment payment, PaymentHelperBean helperObject, Map<String, Object> resultMap)
        throws LandseaException
    {
        Integer billId = payment.getBillId();
        
        // 更新bill表状态及金额
        BillDTO bill = paymentService.updateBillStateAndMoney(billId, payment.getMoney());
        
        String logInfo = getLog(payment, payment.getId());
        LOGGER.info(logInfo + "updateBillStateAndMoney finished.");
        
        if (BillStatusEnum.BIST2.getCode().equals(bill.getBillStatus()))
        {
            // 如果首付款全部完毕，更新合同编号
            Contract contract = updateContractNo(payment, bill, logInfo);
            LOGGER.info(logInfo + "updateContractNo finished. contractNo=" + contract.getContractNo());
            
            // 更新bill的合同编号以及billNo
            Bill bill2 = updateBillNo(contract.getContractNo(), bill.getId(), logInfo);
            LOGGER.info(logInfo + "updateBillNo finished.");
            
            // 修改子项的detailNo
            List<BillDetailDTO> detailList = billDetailReadMapper.selectDetailListById(billId);
            if (CollectionUtils.isNotEmpty(detailList))
            {
                Integer detailNum = 0;
                for (BillDetailDTO billDetail : detailList)
                {
                    detailNum++;
                    BillDetail detail = new BillDetail();
                    detail.setId(billDetail.getId());
                    detail.setDetailNo(bill2.getBillNo() + String.format("%02d", detailNum));
                    detail.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                    billDetailWriteMapper.updateByPrimaryKeySelective(detail);
                    
                    detail.setType(billDetail.getType());
                    // 支付成功-更新独立账单
                    billIndependentService.firUpdateBalanceSheet(billId,
                        contract.getContractNo(),
                        detail,
                        payment.getTime());
                }
                
                // 首期支付成功后开通账户,但换房B合同账户不在此处开
                if (!(contract.getOriginalCId() != null && ReRentType.TURN.equals(contract.getRentType())))
                {
                    AddAccountObject object = new AddAccountObject();
                    object.setRoomId(contract.getRoomId());
                    object.setProjectId(contract.getProjectId());
                    object.setUserId(contract.getUserId());
                    object.setContractId(contract.getId());
                    CurrentAccount currentAccount = prepaymentService.addAccount(object);
                    CurrentThread.set("CURRENTACCOUNT", currentAccount);
                }
                
                billService.updateMontlyOrgContract(contract.getId(), billId);
            }
            
            // 更新授权码为已使用状态
            authCodeService.updateCouponStatusAfterPay(QueryUesdCodeType.CONTRACT, bill.getContractId());
            
            // 重命名合同PDF
            renameContractPdf(contract, payment.getId(), logInfo);
            LOGGER.info(logInfo + "renameContractPdf finished.");
        }
    }
    
    /**
     * [描述]：</br>
     *
     * @param aotuPayBill
     * @param billPayment
     * @throws LandseaException
     *
     */
    @Override
    public void aotoPayDoLocalBusiness(AotuPayBill aotuPayBill, BillPayment billPayment)
        throws LandseaException
    {
        Integer billId = billPayment.getBillId();
        
        // 更新bill表状态及金额
        BillDTO bill = paymentService.updateBillStateAndMoney4AutoPay(aotuPayBill, billPayment);
        String logInfo = "余额自动抵扣首期账单处理|";
        LOGGER.info(logInfo + "更新首期账单状态和金额完毕.");
        
        if (BillStatusEnum.BIST2.getCode().equals(bill.getBillStatus()))
        {
            // 如果首付款全部完毕，更新合同编号
            Contract contract = updateContractNo(billPayment, bill, logInfo);
            LOGGER.info(logInfo + "更新合同编号完毕. contractNo=" + contract.getContractNo());
            
            // 更新bill的合同编号以及billNo
            Bill bill2 = updateBillNo(contract.getContractNo(), bill.getId(), logInfo);
            LOGGER.info(logInfo + "更新账单编号完毕.");
            
            // 修改子项的detailNo
            List<BillDetailDTO> detailList = billDetailReadMapper.selectDetailListById(billId);
            if (CollectionUtils.isNotEmpty(detailList))
            {
                Integer detailNum = 0;
                for (BillDetailDTO billDetail : detailList)
                {
                    detailNum++;
                    BillDetail detail = new BillDetail();
                    detail.setId(billDetail.getId());
                    detail.setDetailNo(bill2.getBillNo() + String.format("%02d", detailNum));
                    detail.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                    billDetailWriteMapper.updateByPrimaryKeySelective(detail);
                    
                    detail.setType(billDetail.getType());
                    // 支付成功-更新独立账单
                    billIndependentService.firUpdateBalanceSheet(billId,
                        contract.getContractNo(),
                        detail,
                        billPayment.getTime());
                }
            }
            
            // 更新授权码为已使用状态
            authCodeService.updateCouponStatusAfterPay(QueryUesdCodeType.CONTRACT, bill.getContractId());
            
            // 重命名合同PDF
            renameContractPdf(contract, billPayment.getId(), logInfo);
            LOGGER.info(logInfo + "重命名合同PDF完毕.");
        }
    }
    
    /**
     * 
     * [简要描述]：生成合同编号更新到账单表</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-07-19)</br>
     *
     * @param payment
     * @param bill
     * @throws LandseaException
     *
     */
    private Contract updateContractNo(BillPayment payment, BillDTO bill, String logInfo)
        throws LandseaException
    {
        try
        {
            // 查询合同
            Contract contract = contractReadMapper.selectByPrimaryKey(bill.getContractId());
            if (null == contract)
            {
                throw LandseaException.createException(PaymentResultCode.E00150011);
            }
            
            Project project = projectReadMapper.selectByPrimaryKey(contract.getProjectId());
            if (null == project)
            {
                throw LandseaException.createException(PaymentResultCode.E00150012);
            }
            
            // 如果支付成功，生成合同编号
            Integer maxContractCode = contractReadMapper.getMaxContractCode();
            String contractSn = paymentService.generateContractNo(project.getPrjCode(), maxContractCode);
            
            // 合同中的支付时间
            contract.setPayTime(payment.getTime());
            
            // 合同改成签约状态
            contract.setStatus(ContractStatusCodeEnum.SIGN.getCode());
            contract.setContractNo(contractSn);
            contract.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            
            contractWriteMapper.updateByPrimaryKeySelective(contract);
            
            // 如果是续租，则要延期门锁密码有效期
            if (contract.getOriginalCId() != null && ReRentType.RERENT.equals(contract.getRentType()))
            {
                LOGGER.info("续租B合同支付首期完成，开始门锁密码有效期延长.ContractId=" + contract.getId());
                // 如果有房租，则要重置密码有效期为房租截止日期,不需要发送短信
                ddLockService.resetPasswordEffectiveTime(contract.getRoomId(), bill.getContractId(), null);
            }
            
            return contract;
        }
        catch (Exception e)
        {
            LOGGER.error(logInfo + "updateContractNo failed.", e);
            throw LandseaException.createException(PaymentResultCode.E00150013, e);
        }
    }
    
    private Bill updateBillNo(String contractSn, Integer billId, String logInfo)
        throws LandseaException
    {
        try
        {
            // 首付款 修改账单号 注意：只修改账单编号，禁止修改其他字段
            Bill billUpdate = new Bill();
            billUpdate.setId(billId);
            billUpdate.setBillNo(contractSn + "01");
            billUpdate.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            billUpdate.setContractNo(contractSn);
            // 此处的创建时间一定不能改，bill表中的createedDtm计算滞纳金要用
            billUpdate.setCreatedDtm(null);
            billUpdate.setCreatedBy(null);
            billWriteMapper.updateByPrimaryKeySelective(billUpdate);
            return billUpdate;
        }
        catch (Exception e)
        {
            LOGGER.error(logInfo + "updateBillNo failed.", e);
            throw LandseaException.createException(PaymentResultCode.E00150010, e);
        }
        
    }
    
    /**
     * 
     * [简要描述]：重命名合同pdf</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-07-19)</br>
     *
     * @param contract
     * @throws LandseaException
     *
     */
    private void renameContractPdf(Contract contract, Integer paymentId, String logInfo)
        throws LandseaException
    {
        try
        {
            Integer userId = SecurityUtils.getCurrentLogin().getUserId();
            String fileName = contract.getContractNo();
            if (contract.getPdfId() != null)
            {
                SystemFile localPdfFile = (SystemFile)fileService.get(contract.getPdfId() + "");
                String pdfName = fileName + ".pdf";
                if (localPdfFile != null)
                {
                    FileTool.reName(localPdfFile.getLocalFullPath(), pdfName);
                }
                SystemFile pdfFile = new SystemFile();
                pdfFile.setId(contract.getPdfId());
                pdfFile.setName(pdfName);
                pdfFile.updateCommonInfo(userId);
                fileWriteMapper.updateByPrimaryKeySelective(pdfFile);
            }
            if (contract.getPdfImg() != null)
            {
                SystemFile localPdfImgFile = (SystemFile)fileService.get(contract.getPdfImg() + "");
                String imgName = fileName + ".jpg";
                FileTool.reName(localPdfImgFile.getLocalFullPath(), imgName);
                SystemFile imgFile = new SystemFile();
                imgFile.setId(contract.getPdfImg());
                imgFile.setName(imgName);
                imgFile.updateCommonInfo(userId);
                fileWriteMapper.updateByPrimaryKeySelective(imgFile);
            }
        }
        catch (Exception e)
        {
            LOGGER.error(logInfo + "Rename Contract PDF failed.", e);
            throw LandseaException.createException(PaymentResultCode.E00150013, e);
        }
    }
    
    @Override
    protected String getProcessClassName()
    {
        return this.getClass().getSimpleName();
    }
}
